package com.airticketbooking.service.serviceImpl;

import com.airticketbooking.common.constant.StatusConstant;
import com.airticketbooking.common.domain.PageQuery;
import com.airticketbooking.common.exception.TicketNotFoundException;
import com.airticketbooking.common.exception.TicketUnavailableException;
import com.airticketbooking.common.utils.BeanUtils;
import com.airticketbooking.common.utils.UserContext;
import com.airticketbooking.dto.OrderDTO;
import com.airticketbooking.po.*;
import com.airticketbooking.vo.OrderVO;
import com.airticketbooking.vo.TicketVO;
import com.airticketbooking.mapper.*;
import com.airticketbooking.service.OrderService;
import com.airticketbooking.service.TicketService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Mr.J
 * @version 1.0.0
 * @date 2024/11/11
 * @desc
 */

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

	private final OrderMapper orderMapper;

	private final TicketService ticketService;


	private final UserMapper userMapper;

	private final OrderWithTicketMapper orderWithTicketMapper;

	private final TicketMapper ticketMapper;

	private final MemberMapper memberMapper;

	private final PointMapper pointMapper;

	private final DiscountTypeMapper discountTypeMapper;

	private final OrderDiscounttypeMapper orderDiscounttypeMapper;

	private final FlightScheduleMapper flightScheduleMapper;

	private final PaymentMapper paymentMapper;

	@Override
	public OrderVO getOrderVOById(Integer orderId) {

		Order order = orderMapper.getOrderById(orderId);

		if (order == null) {
			return null;
		}

		User userById = userMapper.getUserById(order.getUserId());

//根据订单id查询出对应的票的ids
		List<Integer> ticketIds = orderWithTicketMapper.getTicketIdsByOrderId(orderId);

		List<TicketVO> ticketVOS = new ArrayList<>(ticketIds.size());
		//根据票的ids查询出对应的票的信息
		for (Integer ticketId : ticketIds) {
			TicketVO ticketVO = ticketService.getTicketById(ticketId);
			ticketVOS.add(ticketVO);
		}

//		把订单信息和票信息封装到OrderVO中
		OrderVO orderVO = new OrderVO();
		BeanUtils.copyProperties(order, orderVO);
		BeanUtils.copyProperties(userById, orderVO);

		orderVO.setStatus(order.getStatus());
		orderVO.setTicketVOS(ticketVOS);


		return orderVO;
	}

	@Override
	public List<Order> querylist(OrderDTO orderDTO) {


		List<Order> orders = orderMapper.querylist(orderDTO);

		return orders;

	}

	@Override
	@Transactional // 如果使用 Spring，添加事务控制
	public void createOrder(List<Integer> ticketIds) {
		// 验证所有票的有效性
		validateTickets(ticketIds);

		Order order = new Order();
		order.setUserId(UserContext.getUser().intValue());
		order.setStatus(StatusConstant.ORDER_CREATED);
		order.setOrderDateTime(LocalDateTime.now());
		order.setUpadateDateTime(LocalDateTime.now()); // 修正拼写
		order.setPaymentMethod(1); // 默认账户余额支付

		BigDecimal totalTicketPrice = calculateTotalTicketPrice(ticketIds);

		order.setTotalPrice(totalTicketPrice);
		order.setActualAmountDue(BigDecimal.ZERO);
		order.setDiscountAmount(BigDecimal.ZERO);
		order.setDiscountPoint(0);
		order.setEarnedPoints(0);

		orderMapper.addOrder(order);

		// 确保 orderId 被正确赋值
		Integer orderId = order.getOrderId();
		if (orderId == null) {
			throw new RuntimeException("创建订单失败，未能获取自增的订单ID");
		}

		// 更新票的状态并关联到订单
		for (Integer ticketId : ticketIds) {
			orderWithTicketMapper.add(orderId, ticketId);
			Ticket ticket = ticketMapper.getTicketById(ticketId); // 这个查询可以从 validateTickets 拿到
			ticket.setStatus(StatusConstant.TICKET_BOOKED);
			ticketMapper.update(ticket);
		}
	}

	private void validateTickets(List<Integer> ticketIds) {
		for (Integer ticketId : ticketIds) {
			Ticket ticket = ticketMapper.getTicketById(ticketId);

			if (ticket == null) {
				throw new TicketNotFoundException("票ID " + ticketId + " 不存在");
			}

			if (ticket.getStatus() != StatusConstant.TICKET_COULD_BOOK) {
				throw new TicketUnavailableException("票ID " + ticketId + " 不可预定");
			}
		}
	}


	@Override
	public List<Order> getOrdersQuery(OrderDTO orderDTO) {

		List<Order> orders = orderMapper.querylist(orderDTO);


		return orders;

	}


	@Override
	@Transactional // 如果使用 Spring，添加事务控制
	public void confirmOrder(Integer orderId, Integer discountTypeId) {


//			添加订单折扣关联信息
		orderDiscounttypeMapper.add(orderId, discountTypeId);

//		得到总票价
		Order order = orderMapper.getOrderById(orderId);
		BigDecimal totalPrice = order.getTotalPrice();

//		得到折扣金额
		BigDecimal discountAmount = calculateDiscount(totalPrice, discountTypeId, 0);


//		计算实际支付金额
		BigDecimal actualPayment = totalPrice.subtract(discountAmount);

		if (actualPayment.compareTo(BigDecimal.ZERO) <= 0) {
			actualPayment = BigDecimal.ZERO;
		}

		order.setStatus(StatusConstant.ORDER_CONFIRMED);
		order.setOrderDateTime(LocalDateTime.now());
		order.setPaymentMethod(1);
		order.setActualAmountDue(actualPayment);
		order.setTotalPrice(totalPrice);
		order.setDiscountAmount(discountAmount);
		order.setUpadateDateTime(LocalDateTime.now());

		orderMapper.modifyOrder(order);

	}

	@Override
	@Transactional
	public void confirmOrder(Integer orderId, Integer discountTypeId, Integer mortgagePoint) {


//			添加订单折扣关联信息
		orderDiscounttypeMapper.add(orderId, discountTypeId);

//		根据订单id查询出对应的票的ids
		List<Integer> ticketIds = orderWithTicketMapper.getTicketIdsByOrderId(orderId);

//		得到总票价
		BigDecimal totalPrice = calculateTotalTicketPrice(ticketIds);

//		得到折扣金额
		BigDecimal discountAmount = calculateDiscount(totalPrice, discountTypeId, mortgagePoint);


//		计算实际支付金额
		BigDecimal actualPayment = totalPrice.subtract(discountAmount);

		if (actualPayment.compareTo(BigDecimal.ZERO) <= 0) {
			actualPayment = BigDecimal.ZERO;
		}

		Order order = new Order();
		order.setOrderId(orderId);
		order.setStatus(StatusConstant.ORDER_CONFIRMED);
		order.setOrderDateTime(LocalDateTime.now());
		order.setPaymentMethod(1);
		order.setActualAmountDue(actualPayment);
		order.setTotalPrice(totalPrice);
		order.setDiscountAmount(discountAmount);
		order.setDiscountPoint(mortgagePoint);
		order.setUpadateDateTime(LocalDateTime.now());

		orderMapper.modifyOrder(order);


	}


	@Override
	@Transactional
	public void modifyOrder(Integer orderId, Integer oldTicketId, Integer newTicketId) {


//		根据起飞时间判断是否可以改签
		Ticket ticket = ticketMapper.getTicketById(oldTicketId);

		if (ticket == null) {
			throw new IllegalArgumentException("票ID " + oldTicketId + " 不存在");
		}

		if (ticket.getStatus() == StatusConstant.CHANGED) {
			throw new IllegalArgumentException("已经改签过了,不能再改签");
		}

//           根据ticketId查询出对应的班次信息
		FlightSchedule shcedule = flightScheduleMapper.getById(ticket.getScheduleId());

//			判断改签时间是否在起飞时间之前
		if (shcedule.getDepartureTime().isAfter(LocalTime.now().plusMinutes(30))) {
			throw new IllegalArgumentException("改签时间必须在航班起飞时间30分钟之前");
		}

//			更新订单的状态
		Order order = orderMapper.getOrderById(orderId);
		order.setUpadateDateTime(LocalDateTime.now());
		order.setOrderId(orderId);
		orderMapper.modifyOrder(order);

//     改变订单和新旧票的关联

		Ticket newTicket = ticketMapper.getTicketById(newTicketId);
		if (ticket.getStatus() != StatusConstant.PAID) {
			throw new IllegalArgumentException("票ID " + oldTicketId + "此票未支付，不能改签");
		}
		orderWithTicketMapper.delete(orderId, oldTicketId);

		orderWithTicketMapper.add(orderId, newTicketId);

//		重新计算订单的总价格
		List<Integer> ticketIds = orderWithTicketMapper.getTicketIdsByOrderId(orderId);

		BigDecimal totalPrice = calculateTotalTicketPrice(ticketIds);

		// 更新票据状态

		ticket.setUpdateTime(LocalDateTime.now());
		ticket.setStatus(StatusConstant.TICKET_COULD_BOOK);
		ticketMapper.update(ticket);

		newTicket.setUpdateTime(LocalDateTime.now());
		newTicket.setStatus(StatusConstant.PAID);
		ticketMapper.update(newTicket);

//得到原来应该付款的金额
		BigDecimal oldActualAmountDue = order.getActualAmountDue();

		// 计算折扣,这里不退还积分，只退款


		BigDecimal discountAmount = BigDecimal.ZERO;  // 初始化折扣金额

		Member member = memberMapper.getByUserId(UserContext.getUser().intValue());

		if (member != null) {
			Point point = pointMapper.getPointByMemberId(member.getMemberId());

			// 计算折扣类型
			if (point != null) {
				DiscountType discountType = discountTypeMapper.getByPoint(calculatePoint(totalPrice, point.getTotalPoints()));
				if (discountType != null) {
					Integer discountTypeId = discountType.getDiscountTypeId();
					discountAmount = calculateDiscount(totalPrice, discountTypeId, 0);
				}
			}
		}

		BigDecimal actualAmountDue = totalPrice.subtract(discountAmount);

		// 更新订单信息
		order.setTotalPrice(totalPrice);
		order.setDiscountAmount(discountAmount);
		order.setActualAmountDue(actualAmountDue);
		order.setUpadateDateTime(LocalDateTime.now()); // 修正拼写错误

		orderMapper.modifyOrder(order);

		// 给用户退款
		User user = userMapper.getUserById(UserContext.getUser().intValue());
		if (user == null) {
			throw new IllegalArgumentException("用户不存在");
		}

		// 获取用户的账户余额
		BigDecimal accountBalance = user.getAccountBalance();

		// 计算新的账户余额

		BigDecimal refundAmount = oldActualAmountDue.subtract(actualAmountDue); // 退款金额
		accountBalance = accountBalance.add(refundAmount); // 更新账户余额


		// 更新用户的账户余额
		user.setAccountBalance(accountBalance); // 确保将新的余额设置回用户对象
		user.setUpdateDate(LocalDateTime.now());
		userMapper.update(user);

		// 修改支付情况
		Payment payment = paymentMapper.getPaymentByOrderId(orderId);
		if (payment == null) {
			throw new IllegalArgumentException("支付记录不存在");
		}

		payment.setPaymentAmount(actualAmountDue);
		payment.setUpdateDateTime(LocalDateTime.now());
		paymentMapper.modifyPayment(payment);
	}

	@Override
	@Transactional
	public void cancelOrder(Integer orderId, Integer ticketId) {
		// 查询订单状态
		Order order = orderMapper.getOrderById(orderId);
		if (order == null) {
			throw new IllegalArgumentException("订单ID " + orderId + " 不存在");
		}

		// 查询票据
		Ticket ticket = ticketMapper.getTicketById(ticketId);
		if (ticket == null) {
			throw new IllegalArgumentException("票ID " + ticketId + " 不存在");
		}

		// 票据状态为已经完成，不能取消
		if (ticket.getStatus() == StatusConstant.ORDER_FINISHED) {
			throw new IllegalArgumentException("票ID " + ticketId + " 已经完成，不能取消");
		}

		// 航班出发前半小时，不能取消
		FlightSchedule schedule = flightScheduleMapper.getById(ticket.getScheduleId());
		if (schedule == null) {
			throw new IllegalArgumentException("航班ID " + ticket.getScheduleId() + " 不存在");
		}

		// 判断是否在出发前半小时
		LocalTime departureTime = schedule.getDepartureTime();
		if (departureTime.isAfter(LocalTime.now().plusMinutes(30))) {
			throw new IllegalArgumentException("距离航班出发时间不足30分钟，不能取消");
		}

		// 判断订单状态是否为已经支付
		if (ticket.getStatus() != StatusConstant.PAID) {
			throw new IllegalArgumentException("订单状态必须为已经支付");
		}

		// 解除订单和票的关联
		orderWithTicketMapper.delete(orderId, ticketId);

		// 更新票状态
		ticket.setUpdateTime(LocalDateTime.now());
		ticket.setStatus(StatusConstant.TICKET_COULD_BOOK);
		ticketMapper.update(ticket);

		// 更新订单
		BigDecimal totalPrice = order.getTotalPrice(); // 获取订单总价格
		BigDecimal ticketPrice = ticket.getPrice(); // 票价
		totalPrice = totalPrice.subtract(ticketPrice); // 从总价格中减去票价

		BigDecimal oldActualAmountDue = order.getActualAmountDue();

		BigDecimal discountAmount = BigDecimal.ZERO;  // 初始化折扣金额

		Member member = memberMapper.getByUserId(UserContext.getUser().intValue());
		// 计算折扣,这里不退还积分，只退款

		if (member != null) {

			Point point = pointMapper.getPointByMemberId(member.getMemberId());

			// 计算折扣类型
			if (point != null) {
				DiscountType discountType = discountTypeMapper.getByPoint(calculatePoint(totalPrice, point.getTotalPoints()));
				if (discountType != null) {
					Integer discountTypeId = discountType.getDiscountTypeId();
					discountAmount = calculateDiscount(totalPrice, discountTypeId, 0);
				}
			}

		}

		BigDecimal actualAmountDue = totalPrice.subtract(discountAmount);

		// 更新订单信息
		order.setTotalPrice(totalPrice);
		order.setDiscountAmount(discountAmount);
		order.setActualAmountDue(actualAmountDue);
		order.setUpadateDateTime(LocalDateTime.now()); // 修正拼写错误

		orderMapper.modifyOrder(order);

		// 给用户退款
		User user = userMapper.getUserById(UserContext.getUser().intValue());
		if (user == null) {
			throw new IllegalArgumentException("用户不存在");
		}

		// 获取用户的账户余额
		BigDecimal accountBalance = user.getAccountBalance();

		// 计算新的账户余额
		BigDecimal refundAmount = oldActualAmountDue.subtract(actualAmountDue); // 退款金额
		accountBalance = accountBalance.add(refundAmount); // 更新账户余额

		// 更新用户的账户余额
		user.setUpdateDate(LocalDateTime.now());
		user.setAccountBalance(accountBalance); // 确保将新的余额设置回用户对象
		userMapper.update(user);

		// 修改支付情况
		Payment payment = paymentMapper.getPaymentByOrderId(orderId);
		if (payment == null) {
			throw new IllegalArgumentException("支付记录不存在");
		}

		payment.setPaymentAmount(actualAmountDue);
		payment.setUpdateDateTime(LocalDateTime.now());
		paymentMapper.modifyPayment(payment);
	}


	//计算折扣金额,只能选择一种折扣方式
	private BigDecimal calculateDiscount(BigDecimal totalPrice, Integer discountTypeId, Integer mortgagePoint) {

		BigDecimal discount = BigDecimal.ZERO; // 初始化折扣金额为0

		if (discountTypeId == 2) {
			BigDecimal mortgagePointBD = BigDecimal.valueOf(mortgagePoint); // 将 Integer 转换为 BigDecimal
			discount = mortgagePointBD.divide(BigDecimal.valueOf(100)).multiply(BigDecimal.valueOf(200));
		} else if (discountTypeId == 3) {
			discount = discount.add(BigDecimal.valueOf(700));
			// 个人积分扣200的逻辑应明确
			// discount = discount.subtract(BigDecimal.valueOf(200)); // 如果需要
		} else if (discountTypeId == 4) {
			// 确保 totalPrice 是 BigDecimal 类型
			if (totalPrice.compareTo(BigDecimal.ZERO) > 0) { // 确保总价大于0
				discount = totalPrice.multiply(BigDecimal.valueOf(0.2));
			}
		}


		return discount;
	}

	//		计算总票价
	public BigDecimal calculateTotalTicketPrice(List<Integer> ticketIds) {
		BigDecimal ticketPrice = BigDecimal.ZERO;  // 初始化总票价为0

		for (Integer ticketId : ticketIds) {
			Ticket ticket = ticketMapper.getTicketById(ticketId); // 根据票ID获取票信息
			if (ticket == null) {
				throw new IllegalArgumentException("票ID " + ticketId + " 不存在");
			}

			BigDecimal price = ticket.getPrice(); // 获取票价
			ticketPrice = ticketPrice.add(price); // 累加票价
		}

		return ticketPrice; // 返回总票价
	}

	//	积分计算函数
	public Integer calculatePoint(BigDecimal totalPrice, Integer oringalPointpoint) {
		Integer culculatePoint = totalPrice.intValue() / 100;

		return oringalPointpoint + culculatePoint;

	}


}



